﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace TAS
{
    public enum FixMessageType
    {
        MarketDataIncrementalRefresh = 0,
        MarketDataSnapshotFullRefresh,
        Logout,
        Logon,
        SecurityDefintion,
        Unkown
    }

    public enum TransactionType
    {
        Bid = 0,
        Offer,
        Trade,
        OpeningPrice,
        SettlementPrice,
        TradingSessionHighPrice,
        TradingSessionLowPrice,
        TradeVolume,
        OpenInterest,
        SimulatedSell,
        SimulatedBuy,
        EmptyBook,
        SessionHighBid,
        SessionLowOffer,
        FixingPrice,
        CashNote
    }

    public class FixMessageEntity
    {
        public int MajorVersion { get; set; }
        public int MinorVersion { get; set; }
        public FixMessageType MessageType { get; set; }
        public int MessageSequenceNumber { get; set; }
        public DateTime SendingTime { get; set; }
        public int MarketDepthEntriesNumber { get; set; }
        public string FixMessage { get; set; }

        public List<TradeDataEntity> TradeDataEntityList = new List<TradeDataEntity>();

        public bool ParseMessage(string fixMessage)
        {
            int year = 2012, month = 5, day = 7;

            FixMessage = fixMessage;

            TradeDataEntity currentTradeDataEntity = null;

            string[] valuePairs = fixMessage.Split((char)1);

            foreach (string valuePair in valuePairs)
            {
                string[] tagValue = valuePair.Split('=');

                if (tagValue[0].Equals("1128") || tagValue[0].Equals("8"))
                {
                    MajorVersion = 4;
                    MinorVersion = 4;
                    continue;
                }

                if (tagValue[0].Equals("35"))
                {
                    // Other Cases not handled as of now.
                    if (tagValue[1].Equals("X"))
                    {
                        MessageType = FixMessageType.MarketDataIncrementalRefresh;
                    }
                    else
                    {
                        MessageType = FixMessageType.Unkown;
                    }
                    continue;
                }

                if (tagValue[0].Equals("268"))
                {
                    MarketDepthEntriesNumber = Int32.Parse(tagValue[1]);
                    continue;
                }

                if (tagValue[0].Equals("279"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        TradeDataEntityList.Add(currentTradeDataEntity);
                    }

                    currentTradeDataEntity = new TradeDataEntity();
                    currentTradeDataEntity.QuoteCondition = QuoteConditionType.ExchangeBest;

                    currentTradeDataEntity.MarketDataActionType = Int32.Parse(tagValue[1]);
                    continue;
                }

                if (tagValue[0].Equals("48"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        currentTradeDataEntity.InstrumentID = Int32.Parse(tagValue[1]);
                    }
                    continue;
                }

                if (tagValue[0].Equals("107"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        currentTradeDataEntity.SecurityID = tagValue[1];
                    }
                    continue;
                }

                if (tagValue[0].Equals("269"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        switch (tagValue[1][0])
                        {
                            case '0':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.Bid;
                                break;
                            case '1':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.Offer;
                                break;
                            case '2':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.Trade;
                                break;
                            case '4':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.OpeningPrice;
                                break;
                            case '6':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.SettlementPrice;
                                break;
                            case '7':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.TradingSessionHighPrice;
                                break;
                            case '8':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.TradingSessionLowPrice;
                                break;
                            case 'B':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.TradeVolume;
                                break;
                            case 'C':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.OpenInterest;
                                break;
                            case 'E':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.SimulatedSell;
                                break;
                            case 'F':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.SimulatedBuy;
                                break;
                            case 'J':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.EmptyBook;
                                break;
                            case 'N':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.SessionHighBid;
                                break;
                            case 'O':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.SessionLowOffer;
                                break;
                            case 'W':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.FixingPrice;
                                break;
                            case 'X':
                                currentTradeDataEntity.MarketDataEntryType = TransactionType.CashNote;
                                break;
                        }
                    }
                    continue;
                }

                if (tagValue[0].Equals("270"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        currentTradeDataEntity.Price = long.Parse(tagValue[1]); //Double.Parse(tagValue[1]); 
                    }
                    continue;
                }

                if (tagValue[0].Equals("271"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        currentTradeDataEntity.Quantity = Int32.Parse(tagValue[1]);
                    }
                    continue;
                }

                if (tagValue[0].Equals("273"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        int hour = Int32.Parse("" + tagValue[1][0] + "" + tagValue[1][1] + "");
                        int minute = Int32.Parse("" + tagValue[1][2] + "" + tagValue[1][3] + "");
                        int seconds = Int32.Parse("" + tagValue[1][4] + "" + tagValue[1][5] + "");
                        int milliseconds = Int32.Parse("" + tagValue[1][6] + "" + tagValue[1][7] + "" + tagValue[1][8] + "");

                        currentTradeDataEntity.Time = new DateTime(year, month, day, hour, minute, seconds, milliseconds);
                    }
                    continue;
                }

                if (tagValue[0].Equals("1023"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        currentTradeDataEntity.MarketDepthPosition = Int32.Parse(tagValue[1]);
                    }
                    continue;
                }

                if (tagValue[0].Equals("10"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        TradeDataEntityList.Add(currentTradeDataEntity);
                    }
                    continue;
                }

                // 52=20120507182837414

                if (tagValue[0].Equals("52"))
                {
                    year = Int32.Parse("" + tagValue[1][0] + "" + tagValue[1][1] + "" + tagValue[1][2] + "" + tagValue[1][3] + "");
                    month = Int32.Parse("" + tagValue[1][4] + "" + tagValue[1][5] + "");
                    day = Int32.Parse("" + tagValue[1][6] + "" + tagValue[1][7] + "");
                    int hour = Int32.Parse("" + tagValue[1][8] + "" + tagValue[1][9] + "");
                    int minute = Int32.Parse("" + tagValue[1][10] + "" + tagValue[1][11] + "");
                    int seconds = Int32.Parse("" + tagValue[1][12] + "" + tagValue[1][13] + "");
                    int milliseconds = Int32.Parse("" + tagValue[1][14] + "" + tagValue[1][15] + "" + tagValue[1][16] + "");

                    SendingTime = new DateTime(year, month, day, hour, minute, seconds, milliseconds);
                }

                if (tagValue[0].Equals("276"))
                {
                    if (currentTradeDataEntity != null)
                    {
                        if (tagValue[1].Equals("K"))
                        {
                            currentTradeDataEntity.QuoteCondition = QuoteConditionType.Implied;
                        }
                        else
                        {
                            currentTradeDataEntity.QuoteCondition = QuoteConditionType.ExchangeBest;
                        }
                    }
                    continue;
                }
            }

            return true;
        }
    }
}
